home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / scnsrv.zip / NEWNOV.C < prev    next >
Text File  |  1992-10-23  |  17KB  |  743 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <fcntl.h>
  5. #include <io.h>
  6. #include <conio.h>
  7. #include <dir.h>
  8. #include <share.h>
  9. #include <errno.h>
  10. #include <sys\stat.h>
  11. #include <dos.h>
  12. #include "version.h"
  13.  
  14. #pragma hdrstop
  15.  
  16. #include "newnov.h"
  17.  
  18. unsigned int
  19. IntSwap(unsigned int t)
  20. {
  21.     asm {
  22.         mov ax,t
  23.         xchg ah,al
  24.         mov t,ax
  25.     }
  26.     return t;
  27. }
  28.  
  29. unsigned long
  30. LongSwap(unsigned long t)
  31. {
  32.     asm {
  33.         mov ax,word ptr t
  34.         xchg ah,al
  35.         mov bx,word ptr t+2
  36.         mov word ptr t+2,ax
  37.         mov ax,bx
  38.         xchg ah,al
  39.         mov word ptr t,ax
  40.     }
  41.     return t;
  42. }
  43.  
  44. // --------------------------------------------------------------------------
  45. // int GetDirectoryHandle(driveNumber)
  46. //
  47. // Calls the Netware API to get info regarding a drive (A..Z)(1..26) and the
  48. // temporary drives 27 to 32. Returns flags in high byte of int, Directory
  49. //    Handle in the low byte.
  50. //
  51. // CAUTION: Netware numbers drives from ZERO, we number from ONE, and make
  52. //        the adjustment to zero-based within these Netware routines.
  53. // --------------------------------------------------------------------------
  54.  
  55. int
  56. GetDirectoryHandle(driveNumber)
  57. {
  58.     int res;
  59.  
  60.     _DX = (unsigned) driveNumber-1;
  61.     _AX = 0xE900;
  62.     geninterrupt(0x21);
  63.     res = _AX;
  64.  
  65.     return res;
  66. }
  67.  
  68. int
  69. GetPreferredConnectionID(void)
  70. {
  71.     _AX = 0xF001;
  72.     geninterrupt(0x21);
  73.     return _AL;
  74. }
  75.  
  76. void
  77. SetPreferredConnectionID(int connectionID)
  78. {
  79.     _AX = 0xF000;
  80.     _DL = connectionID;
  81.     geninterrupt(0x21);
  82. }
  83.  
  84. struct ConnectionIDTable far *
  85. GetConnIDTable(void)
  86. {
  87.     unsigned segp, offp;
  88.  
  89.     _AX = 0xEF03;
  90.  
  91.     asm push es
  92.     asm push si
  93.  
  94.     geninterrupt(0x21);
  95.  
  96.     asm mov segp,es
  97.     asm mov offp,si
  98.     asm pop si
  99.     asm pop es
  100.  
  101.     return MK_FP(segp,offp);
  102. }
  103.  
  104. struct DriveConnectionIDTable far *
  105. GetDriveConnIDTable(void)
  106. {
  107.     unsigned segp, offp;
  108.  
  109.     _AX = 0xEF02;
  110.  
  111.     asm push es
  112.     asm push si
  113.  
  114.     geninterrupt(0x21);
  115.  
  116.     asm mov segp,es
  117.     asm mov offp,si
  118.     asm pop si
  119.     asm pop es
  120.  
  121.     return MK_FP(segp,offp);
  122. }
  123.  
  124. struct FileServerNameTable far *
  125. GetFSNameTable(void)
  126. {
  127.     unsigned segp, offp;
  128.  
  129.     _AX = 0xEF04;
  130.  
  131.     asm push es
  132.     asm push si
  133.  
  134.     geninterrupt(0x21);
  135.  
  136.     asm mov segp,es
  137.     asm mov offp,si
  138.     asm pop si
  139.     asm pop es
  140.  
  141.     return MK_FP(segp,offp);
  142. }
  143.  
  144. int
  145. GetConnectionID(char *serverName, int *connectionIDP)
  146. {
  147.     int i;
  148.     struct ConnectionIDTable far *idtp = GetConnIDTable();
  149.     struct FileServerNameTable far *nmtp = GetFSNameTable();
  150.  
  151.  
  152.     // loop thru the file server name table/connection ID table, looking for
  153.     // a fileservername
  154.     strupr(serverName);
  155.  
  156.     for (i=1; i<=8; i++, idtp++) {
  157.  
  158.         if (
  159.                 (idtp->slotInUse) &&
  160.                 (idtp->connectionNumber != 0xFF) &&
  161.                 (idtp->connectionStatus == 0xFF) &&
  162.                 (!strcmp(serverName, nmtp->ServerName[i-1]))
  163.             )
  164.         {
  165.             *connectionIDP = i;
  166.             return 0;
  167.         }
  168.  
  169.     }
  170.     return NERR_NOCONN;
  171.  
  172. }
  173.  
  174. int
  175. GetNextServer(char *serverName, int *connectionIDP)
  176. {
  177.     int i = *connectionIDP + 1;
  178.     struct ConnectionIDTable far *idtp = GetConnIDTable() + i - 1;
  179.     struct FileServerNameTable far *nmtp = GetFSNameTable();
  180.  
  181.  
  182.     // loop thru the file server name table/connection ID table, looking for
  183.     // a valid table entry. Start with the previous connection index. (Use
  184.     //    0 to begin a new search.
  185.  
  186.     for (; i<=8; i++, idtp++) {
  187.  
  188.         if (
  189.                 (idtp->slotInUse) &&
  190.                 (idtp->connectionNumber != 0xFF) &&
  191.                 (idtp->connectionStatus == 0xFF)
  192.             )
  193.         {
  194.             strcpy(serverName, nmtp->ServerName[i-1]);
  195.             *connectionIDP = i;
  196.             return 0;
  197.         }
  198.  
  199.     }
  200.     return NERR_NOCONN;
  201.  
  202. }
  203.  
  204. // --------------------------------------------------------------------------
  205. // int FindMappedDrive(char *serverName, char *volumeName, int *driveP, char *path)
  206. //
  207. // Calls the Netware APIs to find the first network-mapped drive that is
  208. // currently connected to a given server and volume. Useful for conserving
  209. // drive letters. Only permanent drives are examined.
  210. //
  211. // If the optional path parameter is non-null, then a drive won't be accepted
  212. //    in the search, unless the given path is accessible from that drive. This
  213. //    is to prevent problems with fake root mappings on Netware 386 systems.
  214. //
  215. // Return drive number (1..26) if OK, or -1 if couldn't find such a drive,
  216. // or if an error occurs during the search.
  217. // --------------------------------------------------------------------------
  218.  
  219. int
  220. FindMappedDrive(char *serverName, char *volumeName, char *path)
  221. {
  222.     int i, connID;
  223.     int savedisk = getdisk();
  224.  
  225.     struct DriveConnectionIDTable far *dcidtp;
  226.     char pathName[255];
  227.  
  228.     strupr(serverName); strupr(volumeName);
  229.  
  230.     // First, determine the connection ID of the server we need.
  231.     if (GetConnectionID(serverName, &connID))
  232.         return -1;
  233.  
  234.     // Get a pointer to the drive connection ID table.
  235.     dcidtp = GetDriveConnIDTable();
  236.     if (!dcidtp)
  237.         return -1;
  238.  
  239.     // Now, look at each drive that is mapped to that server (i.e., the
  240.     //        connection ID in the Drive Connection ID table matches).
  241.     for (i=1; i<=26; i++) {
  242.  
  243.         if (dcidtp->connID[i-1] == connID) {
  244.  
  245.             // Found a possible match. Check the volume it's mapped to...
  246.             //    (We get the dir path for the handle associated with the drive,
  247.             //     then see if the beginning of the path matches the volumeName).
  248.             if (!GetDirectoryPath(GDH_HANDLE(GetDirectoryHandle(i)), pathName)) {
  249.  
  250.                 if
  251.                     (
  252.                         // the volume name mapped to matches what we want...
  253.                         !strncmp(pathName, volumeName, strlen(volumeName)) &&
  254.                         (pathName[strlen(volumeName)] == ':') &&
  255.  
  256.                         // and if the optional path access is achievable...
  257.                         (
  258.                             path &&
  259.                             (setdisk(i-1), !access(path, 0))
  260.                         )
  261.                     )
  262.                 {
  263.                     setdisk(savedisk);
  264.                     return i;
  265.                 }
  266.             }
  267.             else
  268.                 continue;
  269.         }
  270.  
  271.     }
  272.     setdisk(savedisk);
  273.     return -1;
  274. }
  275.  
  276. // --------------------------------------------------------------------------
  277. // int AllocateDirHandle(char *volumeName,
  278. //                                                int drive, int handle, int opcode);
  279. //
  280. // Calls the Netware API to allocate a dir handle to a SERVER\VOLUME:
  281. // combination, or to deallocate a previously-allocated handle.
  282. //
  283. // --------------------------------------------------------------------------
  284.  
  285. int
  286. AllocateDirHandle(char *volumeName, int drive, int handle, int opcode)
  287. {
  288.     struct AllocateDirHandleRequest req;
  289.     struct NovellReply reply = { 2, 0, 0 };
  290.     unsigned segq, offq, segp, offp, res;
  291.  
  292.     memset(req.path, 0, sizeof(req.path));
  293.     strcat(req.path, volumeName);
  294.     strcat(req.path, ":");
  295.     strupr(req.path);
  296.  
  297.     req.pathLength     = strlen(req.path);
  298.     req.length             = sizeof(req) - 2;
  299.     req.reqFcnCode     = opcode;
  300.     req.dirHandle         = handle;
  301.     req.driveLetter     = drive + 'A' - 1;
  302.  
  303.     if (opcode == ADH_DEALLOC)
  304.         reply.length = 0;
  305.  
  306.     segq = FP_SEG((void far *) &req);
  307.     offq = FP_OFF((void far *) &req);
  308.  
  309.     segp = FP_SEG((void far *) &reply);
  310.     offp = FP_OFF((void far *) &reply);
  311.  
  312.     asm push di
  313.     asm push si
  314.     asm push es
  315.     asm push ds
  316.     asm mov ax,0xe200
  317.     asm mov si,offq
  318.     asm mov di,offp
  319.     asm mov es,segp
  320.     asm mov ds,segq
  321.     asm int 0x21
  322.     asm pop ds
  323.     asm pop es
  324.     asm pop si
  325.     asm pop di
  326.     asm mov ah,0
  327.     asm mov res,ax
  328.  
  329.     return res;
  330. }
  331.  
  332. // --------------------------------------------------------------------------
  333. // int GetDirectoryPath(int dirHandle, char *pathOutBuf);
  334. //
  335. // Calls the Netware API to find a dir handle's path. Puts the path
  336. // into pathOutBuf, which must be at least 255 bytes.
  337. //
  338. // --------------------------------------------------------------------------
  339.  
  340. int
  341. GetDirectoryPath(int dirHandle, char *pathOutBuf)
  342. {
  343.     struct GetDirectoryPathRequest req;
  344.     struct GetDirectoryPathReply reply;
  345.     unsigned segq, offq, segp, offp, res;
  346.  
  347.     reply.length         = sizeof(reply) - 2;
  348.  
  349.     req.length             = sizeof(req) - 2;
  350.     req.reqFcnCode     = 1;                                // Get Dir Handle's Path...
  351.     req.dirHandle         = dirHandle;
  352.  
  353.  
  354.     segq = FP_SEG((void far *) &req);
  355.     offq = FP_OFF((void far *) &req);
  356.  
  357.     segp = FP_SEG((void far *) &reply);
  358.     offp = FP_OFF((void far *) &reply);
  359.  
  360.     asm push di
  361.     asm push si
  362.     asm push es
  363.     asm push ds
  364.     asm mov ax,0xe200
  365.     asm mov si,offq
  366.     asm mov di,offp
  367.     asm mov es,segp
  368.     asm mov ds,segq
  369.     asm int 0x21
  370.     asm pop ds
  371.     asm pop es
  372.     asm pop si
  373.     asm pop di
  374.     asm mov ah,0
  375.     asm mov res,ax
  376.  
  377.     // if successful, move the path into the callers buffer
  378.     if (!res)
  379.     {
  380.         memcpy(pathOutBuf, reply.path, reply.dirPathLen);
  381.         pathOutBuf[reply.dirPathLen] = '\0';
  382.     }
  383.     else
  384.         sprintf(pathOutBuf, "badHandle, err = 0x%2.2x", res);
  385.  
  386.     return res;
  387. }
  388.  
  389. int
  390. GetVolumeName(char *volName, int volIndex)
  391. {
  392.     struct GetVolumeNameRequest req;
  393.     struct GetVolumeNameReply reply;
  394.  
  395.     unsigned segq, offq, segp, offp, res;
  396.  
  397.     reply.length         = sizeof(reply) - 2;
  398.  
  399.     req.length             = sizeof(req) - 2;
  400.     req.function         = 6;
  401.     req.volNumber        = volIndex;
  402.  
  403.  
  404.     segq = FP_SEG((void far *) &req);
  405.     offq = FP_OFF((void far *) &req);
  406.  
  407.     segp = FP_SEG((void far *) &reply);
  408.     offp = FP_OFF((void far *) &reply);
  409.  
  410.     asm push di
  411.     asm push si
  412.     asm push es
  413.     asm push ds
  414.     asm mov ax,0xe200
  415.     asm mov si,offq
  416.     asm mov di,offp
  417.     asm mov es,segp
  418.     asm mov ds,segq
  419.     asm int 0x21
  420.     asm pop ds
  421.     asm pop es
  422.     asm pop si
  423.     asm pop di
  424.     asm mov ah,0
  425.     asm mov res,ax
  426.  
  427.     // if successful, move the path into the callers buffer
  428.     if (!reply.volnameLength)
  429.         res = -1;
  430.  
  431.     if (!res)
  432.     {
  433.         memcpy(volName, reply.volName, reply.volnameLength);
  434.         volName[reply.volnameLength] = '\0';
  435.     }
  436.  
  437.     return res;
  438. }
  439.  
  440. // --------------------------------------------------------------------------
  441. //    void DumpDriveMapping(void)
  442. // --------------------------------------------------------------------------
  443.  
  444. void
  445. DumpDriveMapping(void)
  446. {
  447.     int dirHandle, handleType, driveNum, driveConn, 
  448.                     saveConn = GetPreferredConnectionID();
  449.     char path[255];
  450.     struct DriveConnectionIDTable far *dcidtp = GetDriveConnIDTable();
  451.     struct FileServerNameTable far *fsnmtp = GetFSNameTable();
  452.  
  453.     cprintf("------------ Dump Drive Mapping ----------------------\r\n");
  454.     for (driveNum = 1; driveNum <= 32; driveNum++) {
  455.  
  456.         dirHandle = GetDirectoryHandle(driveNum);
  457.         handleType = GDH_MASK(dirHandle);
  458.         dirHandle  = GDH_HANDLE(dirHandle);
  459.         driveConn  = dcidtp->connID[driveNum-1];
  460.  
  461.         switch (handleType) {
  462.  
  463.             case GDH_LOCAL:
  464.                 break;
  465.  
  466.             case GDH_UNMAPPED:
  467.                 break;
  468.  
  469.             case GDH_MAP_PERM:
  470.                 handleType = 'P';
  471.                 goto printit;
  472.  
  473.             case GDH_MAP_TEMP:
  474.                 handleType = 'T';
  475.  
  476.             printit:
  477.                 SetPreferredConnectionID(driveConn);
  478.                 GetDirectoryPath(dirHandle, path);
  479.                 cprintf("Drive %c: (#%d/%c) %s\\%s\r\n", driveNum+'A'-1, driveNum, handleType,
  480.                     fsnmtp->ServerName[driveConn-1], path);
  481.                 break;
  482.  
  483.             default:
  484.                 break;
  485.         }
  486.  
  487.     }
  488.     SetPreferredConnectionID(saveConn);
  489.     getch();
  490. }
  491.  
  492. // --------------------------------------------------------------------------
  493. // int   NovMapDrive(int *drive, char *server, char *volume)
  494. //
  495. //    Maps an unmapped drive number to a server and volume. Returns one of the 
  496. // NERR codes upon error, or 0 if OK. Returns NERR_NODRIVE if all drives
  497. //    are already mapped.
  498. //
  499. // int NovUnMapDrive(int drive);
  500. //
  501. // Unmaps a drive mapped by NovMapDrive(). Returns 0 if OK, or NERR_xxxx if
  502. //    error.
  503. // --------------------------------------------------------------------------
  504.  
  505. int
  506. NovMapDrive(int *drive, char *server, char *volume)
  507. {
  508.     int res;
  509.     int savePrefConnID, newConnID;
  510.  
  511.     // Find the server...
  512.     if ((res = GetConnectionID(server, &newConnID)) != 0)
  513.         return NERR_NOCONN;
  514.  
  515.     // change to that one for preferred connection
  516.     savePrefConnID = GetPreferredConnectionID();
  517.     SetPreferredConnectionID(newConnID);
  518.  
  519.     for (*drive = 1; *drive < 26; (*drive)++)
  520.     {
  521.         if (GDH_MASK(GetDirectoryHandle(*drive)) == GDH_UNMAPPED)
  522.             break;
  523.     }
  524.     if (*drive >= 26) {
  525.         SetPreferredConnectionID(savePrefConnID);
  526.         return NERR_NODRIVE;
  527.     }
  528.  
  529.     res = AllocateDirHandle(volume, *drive, 0, ADH_PERM);
  530.     SetPreferredConnectionID(savePrefConnID);
  531.     return res;
  532. }
  533.  
  534. int
  535. NovUnMapDrive(int drive, char *server)
  536. {
  537.     int res;
  538.     int dirhandle;
  539.  
  540.     int savePrefConnID, newConnID;
  541.  
  542.     // Find the server...
  543.     if ((res = GetConnectionID(server, &newConnID)) != 0)
  544.         return NERR_NOCONN;
  545.  
  546.     // change to that one for preferred connection
  547.     savePrefConnID = GetPreferredConnectionID();
  548.     SetPreferredConnectionID(newConnID);
  549.  
  550.     dirhandle = GDH_HANDLE(GetDirectoryHandle(drive));
  551.  
  552.     res = AllocateDirHandle("", drive, dirhandle, ADH_DEALLOC);
  553.     SetPreferredConnectionID(savePrefConnID);
  554.     return res;
  555. }
  556.  
  557. int
  558. GetFileInfo(char *path, struct NovellFileInfo *nfip, int in_seqnum)
  559. {
  560.     struct GetFileInfoRequest req;
  561.     struct GetFileInfoReply   reply;
  562.  
  563.     unsigned segq, segp, offq, offp;
  564.     int res = 0;
  565.  
  566.     // init the request struct with the path...
  567.     strcpy(req.path, path);
  568.     req.pathLen =         strlen(path);
  569.  
  570.     req.length =         sizeof(req) - 2;
  571.     req.function =     0x0F;
  572.     req.seqnum =         in_seqnum;
  573.     req.dirHandle =     0;
  574.     req.searchAttribs = 0x6;     // djdjdjdj hack, s/b a parameter....
  575.  
  576.     // initialize the reply packet...
  577.     reply.length = sizeof(reply) - 2;
  578.  
  579.     // make the call!
  580.     segq = FP_SEG((void far *) &req);
  581.     offq = FP_OFF((void far *) &req);
  582.  
  583.     segp = FP_SEG((void far *) &reply);
  584.     offp = FP_OFF((void far *) &reply);
  585.  
  586.     asm push di
  587.     asm push si
  588.     asm push es
  589.     asm push ds
  590.     asm mov ax,0xe300
  591.     asm mov si,offq
  592.     asm mov di,offp
  593.     asm mov es,segp
  594.     asm mov ds,segq
  595.     asm int 0x21
  596.     asm pop ds
  597.     asm pop es
  598.     asm pop si
  599.     asm pop di
  600.     asm mov ah,0
  601.     asm mov res,ax
  602.  
  603.     // If successful, copy the results to the file info struct....
  604.     if (!res)
  605.     {
  606.         memcpy(nfip->filename, reply.filename, sizeof(nfip->filename));
  607.  
  608.         nfip->fileAttributes             = reply.fileAttributes;
  609.         nfip->extendedFileAttributes     = reply.extendedFileAttributes;
  610. //        nfip->reserved                     = reply.reserved;
  611.         nfip->creationDate                 = reply.creationDate;
  612.         nfip->accessDate                     = reply.accessDate;
  613.         nfip->updateTime                     = reply.updateTime;
  614.         nfip->ownerID                         = reply.ownerID;
  615.         nfip->archiveTime                 = reply.archiveTime;
  616.         nfip->seqnum                        = reply.seqnum;
  617.  
  618.         nfip->fileSize                        = reply.fileSize;
  619.  
  620.         memcpy(nfip->reserved_buf, &(reply.reserved_buf), 
  621.             sizeof(nfip->reserved_buf));
  622.     }
  623.  
  624.     return res;
  625. }
  626.  
  627. int
  628. SetFileInfo(char *path, struct NovellFileInfo *nfip)
  629. {
  630.     struct SetFileInfoRequest req;
  631.     int reply = 0;
  632.  
  633.     unsigned segq, segp, offq, offp;
  634.     int res = 0;
  635.  
  636.     // init the request struct with file info...
  637.  
  638.     strcpy(req.path, path);
  639.     req.pathLen =         strlen(path);
  640.  
  641.     req.fileAttributes             = nfip->fileAttributes;
  642.     req.extendedFileAttributes     = nfip->extendedFileAttributes;
  643.     req.reserved                     = 0; // nfip->reserved;
  644.     req.creationDate                 = nfip->creationDate;
  645.     req.accessDate                     = nfip->accessDate;
  646.     req.updateTime                     = nfip->updateTime;
  647.     req.ownerID                         = nfip->ownerID;
  648. //req.ownerID = 0;
  649.  
  650.     req.archiveTime                 = nfip->archiveTime;
  651.  
  652. //    memcpy(&(req.reserved_buf), nfip->reserved_buf,
  653. //        sizeof(req.reserved_buf));
  654.  
  655.     memset(&(req.reserved_buf), 0, sizeof(req.reserved_buf));
  656.  
  657.     req.length =         sizeof(req) - sizeof(req.path) + req.pathLen - 2;
  658.     req.function =     0x10;
  659.     req.dirHandle =     0;
  660.     req.searchAttribs = 6;     // djdjdjdj hack, s/b a parameter....
  661.  
  662.     // make the call!
  663.     segq = FP_SEG((void far *) &req);
  664.     offq = FP_OFF((void far *) &req);
  665.  
  666.     segp = FP_SEG((void far *) &reply);
  667.     offp = FP_OFF((void far *) &reply);
  668.  
  669.     asm push di
  670.     asm push si
  671.     asm push es
  672.     asm push ds
  673.     asm mov ax,0xe300
  674.     asm mov si,offq
  675.     asm mov di,offp
  676.     asm mov es,segp
  677.     asm mov ds,segq
  678.     asm int 0x21
  679.     asm pop ds
  680.     asm pop es
  681.     asm pop si
  682.     asm pop di
  683.     asm mov ah,0
  684.     asm mov res,ax
  685.  
  686.     return res;
  687. }
  688.  
  689. // If this call returns success, then it might actually be out of directories.
  690. // This can be detected because the subdirNumber won't change.
  691.  
  692. int
  693. GetDirInfo(char *path, struct ScanDirInfoReply *dip)
  694. {
  695.     struct ScanDirInfoRequest req;
  696.  
  697.     unsigned segq, segp, offq, offp;
  698.     int res = 0;
  699.  
  700.     // init the request struct with the path...
  701.     strcpy(req.path, path);
  702.     req.pathLen =         strlen(path);
  703.  
  704. //    req.length =         sizeof(req) - 2;
  705.     req.length =         sizeof(req) - sizeof(req.path) + req.pathLen - 2;
  706.     req.function =     0x02;
  707.     req.subdirNumber =         IntSwap(dip->subdirNumber+1);
  708.     req.dirHandle =     0;
  709.  
  710.     // initialize the reply packet...
  711.     dip->length = sizeof(*dip) - 2;
  712.  
  713.     // make the call!
  714.     segq = FP_SEG((void far *) &req);
  715.     offq = FP_OFF((void far *) &req);
  716.  
  717.     segp = FP_SEG((void far *) dip);
  718.     offp = FP_OFF((void far *) dip);
  719.  
  720.     asm push di
  721.     asm push si
  722.     asm push es
  723.     asm push ds
  724.     asm mov ax,0xe200
  725.     asm mov si,offq
  726.     asm mov di,offp
  727.     asm mov es,segp
  728.     asm mov ds,segq
  729.     asm int 0x21
  730.     asm pop ds
  731.     asm pop es
  732.     asm pop si
  733.     asm pop di
  734.     asm mov ah,0
  735.     asm mov res,ax
  736.  
  737.     dip->subdirNumber = IntSwap(dip->subdirNumber);
  738.  
  739.     return res;
  740. }
  741.  
  742.  
  743.